package structure;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Queue;

import utilities.rle2dUtilities;

public class RLEBuffer {
	
	private final static int MAX_BUFFER_LEN = 255;
	
	private Queue<Integer> buffer;
	private ArrayList<Byte> returnSeq;
	private int count;
	
	private int prevVal = -1;
	private int seriesLen = 1;
	
	private int MARKER;
	
	public RLEBuffer(int marker) {
		returnSeq = new ArrayList<Byte>();
		buffer = new LinkedList<Integer>();
		MARKER = marker;
	}
	
	public void addValue(Integer value) {
		
		if(buffer.size()>=MAX_BUFFER_LEN) {
			rle();
		}
		buffer.add(value);
		
	}
	
	public void finish(){
		while(!buffer.isEmpty()){
			rle();
		}	
	}
	
	public void rle () {
		int color;
		if(!buffer.isEmpty()){
			color = buffer.remove();
			if (color == prevVal) {
				if(seriesLen >= rle2dUtilities.HSERIES_MAX_LEN) {
					returnSeq.add((byte)MARKER);
					returnSeq.add((byte)seriesLen);
					returnSeq.add((byte)prevVal);
					seriesLen = 1;
					count++;
				}
				else {
					seriesLen++;
				}
			}
			else {
				if(seriesLen > rle2dUtilities.HSERIES_MIN_LEN){
					returnSeq.add((byte)MARKER);
					returnSeq.add((byte)seriesLen);
					returnSeq.add((byte)prevVal);
					count++;
				}
				else {
					if (prevVal == MARKER) {
						if (seriesLen < rle2dUtilities.H_SERIES_MARKER_MIN_LEN) {
							returnSeq.add((byte)MARKER);
							returnSeq.add((byte)rle2dUtilities.H_SERIES_MARKER_COLOR);
						}
						else
						{
							returnSeq.add((byte)MARKER);
							returnSeq.add((byte)seriesLen);
							returnSeq.add((byte)prevVal);
						}
					}
					else {
						if(prevVal != -1 ) {
							for (int i=0;i<seriesLen;i++)
								returnSeq.add((byte)prevVal);
						}
					}
				}
				seriesLen = 1;
			}
			prevVal = color;
		}
		
	}

	public ArrayList<Byte> getReturnSeq() {
		return returnSeq;
	}

	public int getCount() {
		return count;
	}
}
